<script setup lang="ts" name="DevelopWebsocket">
import useSocket from '@/utils/websocket/useSocket'
import { socketOptions } from '@/utils/websocket/helper'
import { cloneDeep } from 'lodash-es'
import { UserApi } from '@/api/system/user'
import { formatDate } from '@/utils/dateUtil'

const { VITE_WEBSOCKET_WSS } = import.meta.env
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
/** 监听接收到的数据 */
const messageList = ref([] as { time: number; text: string }[]) // 消息列表
const messageReverseList = computed(() => messageList.value.slice().reverse())
const onMessageCallback = (res: any) => {
  console.log(res)
  if (!res) {
    return
  }
  try {
    // 1. 收到心跳
    if (res.data === 'pong') {
      return
    }
    if (!res.type) {
      message.error(t('develop.websocket.error', 'type') + res)
      return
    }
    if (res.type === 'demo-message-send') {
      const single = res.data.single
      if (single) {
        messageList.value.push({
          text: `【单发】用户编号(${res.data.fromUserId})：${res.data.text}`,
          time: new Date().getTime()
        })
      } else {
        messageList.value.push({
          text: `【群发】用户编号(${res.data.fromUserId})：${res.data.text}`,
          time: new Date().getTime()
        })
      }
      return
    }
    // 2.3 消息类型：notice-push
    if (res.type === 'notice-push') {
      messageList.value.push({
        text: `【系统通知】：${res.data.title}`,
        time: new Date().getTime()
      })
      return
    }
    message.error(t('develop.websocket.error', 'untreated') + res)
  } catch (error) {
    message.error(t('develop.websocket.error', 'exception') + res)
    console.error(error)
  }
}

const { open, close, send } = useSocket(onMessageCallback)
const socket: any = ref(cloneDeep(socketOptions()))
socket.value.url = ''
const server = ref(VITE_WEBSOCKET_WSS + socket.value.url)

const getIsOpen = computed(() => socket.value.status === 'OPEN') // WebSocket 连接是否打开
const getTagColor = computed(() => (getIsOpen.value ? 'success' : 'danger')) // WebSocket 连接的展示颜色


/** 发送消息 */
const sendText = ref('') // 发送内容
const sendUserId = ref('') // 发送人
const handlerSend = () => {
  // 1.1 先 JSON 化 message 消息内容
  const messageContent = JSON.stringify({
    text: sendText.value,
    toUserId: sendUserId.value
  })
  // 1.2 再 JSON 化整个消息
  socket.value.message = {
    type: 'demo-message-send',
    content: messageContent,
    time: new Date().getTime()
  }
  // 2. 最后发送消息
  send(socket)
  sendText.value = ''
}

/** 切换 websocket 连接状态 */
const toggleConnectStatus = () => {
  if (getIsOpen.value) {
    close(socket)
  } else {
    open(socket)
  }
}

/** 初始化 **/
const userList = ref<any[]>([]) // 用户列表

onMounted(async () => {
  // 获取用户列表
  userList.value = await UserApi.simple()
})
</script>

<template>
  <PageCard direction="row">
    <el-card class="flex-1">
      <template #header>
        <div class="card-header">
          <span>{{ t('develop.websocket', 'connect') }}</span>
        </div>
      </template>
      <div class="flex items-center">
        <span class="mr-4 text-lg font-medium">{{ t('develop.websocket', 'status') }}</span>
        <el-tag :type="getTagColor">{{ socket.status }}</el-tag>
      </div>
      <div class="flex mt-20px">
        <el-input v-model="server" disabled>
          <template #prepend>{{ t('develop.websocket', 'address') }}</template>
        </el-input>
        <el-button :type="getIsOpen ? 'danger' : 'primary'" class="ml-12px" @click="toggleConnectStatus">
          {{ getIsOpen ? t('develop.websocket', 'close') : t('develop.websocket', 'open') }}
        </el-button>
      </div>
      <el-divider />
      <p class="mt-4 text-lg font-medium">{{ t('develop.websocket.input', 'title') }}</p>
      <el-input v-model="sendText" :autosize="{ minRows: 2, maxRows: 4 }" :disabled="!getIsOpen" clearable :placeholder="t('develop.websocket.input', 'message')" type="textarea" />
      <el-select v-model="sendUserId" class="mt-4" :disabled="!getIsOpen" :placeholder="t('develop.websocket.input', 'userId')">
        <el-option key="" :label="t('develop.websocket.input', 'all')" value="" />
        <el-option v-for="user in userList" :key="user.id" :label="user.nickname" :value="user.id" />
      </el-select>
      <el-button :disabled="!getIsOpen" block class="mt-4 w-full" type="primary" @click="handlerSend">{{ t('develop.websocket.input', 'send') }}</el-button>
    </el-card>
    <el-card class="flex-1 ml-20px">
      <template #header>
        <div class="card-header">
          <span>{{ t('develop.websocket.record', 'title') }}</span>
        </div>
        <el-scrollbar>
          <ul>
            <li v-for="msg in messageReverseList" :key="msg.time" class="mt-2">
              <div class="flex items-center">
                <span class="text-primary mr-2 font-medium">{{ t('develop.websocket.record', 'message') }}</span>
                <span>{{ formatDate(msg.time as any) }}</span>
              </div>
              <div>
                {{ msg.text }}
              </div>
            </li>
          </ul>
        </el-scrollbar>
      </template>
    </el-card>
  </PageCard>
</template>

<style scoped lang="scss"></style>
